package com.yequan.springmvc.servlet;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yequan.springframework.config.ClasspathResource;
import com.yequan.springframework.config.Resource;
import com.yequan.springframework.factory.XmlBeanFactory;
import com.yequan.springmvc.handleradapter.iface.HandlerAdapter;
import com.yequan.springmvc.handlermapping.iface.HandlerMapping;

/**
 * 
 * @author 灭霸詹
 *
 */
public class DispatcherServlet extends AbstractsHttpServlet {
	private static final long serialVersionUID = 1L;

	private XmlBeanFactory beanFactory;

	/**
	 * HandlerMapping的策略集合
	 */
	private List<HandlerMapping> handlerMappings = new ArrayList<>();
	/**
	 * HandlerAdapter的策略集合
	 */
	private List<HandlerAdapter> handlerAdapters = new ArrayList<>();

	@Override
	public void init(ServletConfig config) throws ServletException {
		String location = config.getInitParameter("contextConfigLocation");
		initSpringContainer(location);
		// 初始化处理器映射器策略集合
		initHandlerMappings();
		// 初始化处理器适配器策略集合
		initHandlerAdapters();
	}

	private void initHandlerAdapters() {
		
//		handlerAdapters = beanFactory.getBeansOfType(HandlerAdapter.class);
	}

	private void initSpringContainer(String location) {
		Resource resource = new ClasspathResource(location);
		beanFactory = new XmlBeanFactory(resource);
	}

	private void initHandlerMappings() {
		// handlerMappings.add(new BeanNameUrlHandlerMapping());
		// handlerMappings.add(new SimpleUrlHandlerMapping());

//		handlerMappings = beanFactory.getBeansOfType(HandlerMapping.class);
	}

	/**
	 * 核心逻辑
	 * 
	 * @param request
	 * @param response
	 */

	@Override
	public void doDispatch(HttpServletRequest request, HttpServletResponse response) {
		try {
			// 查找处理器
			Object handler = getHandler(request);
			if (handler == null) {
				return;
			}
			// 执行处理器
			// 利用了处理器适配器去执行处理器？
			// 为什么要使用处理器适配器去执行处理器呢？处理器适配器又是个什么呢?
			// 答：因为处理器的类型不统一
			// 在DispatcherServlet类中更新见到一个统一的类型（HandlerAdapter）来执行

			// 使用策略模式，查找合适的处理器适配器
			HandlerAdapter ha = getHandlerAdapter(handler);
			if (ha == null) {
				return;
			}

			// 请求处理器适配器执行处理器
			ha.handleRequest(handler, request, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 根据处理器，通过策略模式，查找对应的处理器适配器
	 * 
	 * @param handler
	 * @return
	 */
	private HandlerAdapter getHandlerAdapter(Object handler) {
		if (handlerAdapters != null) {
			for (HandlerAdapter handlerAdapter : handlerAdapters) {
				if (handlerAdapter.supports(handler)) {
					return handlerAdapter;
				}
			}
		}
		return null;
	}

	/**
	 * 根据请求查找对应的处理器
	 * 
	 * @param request
	 * @return
	 */
	private Object getHandler(HttpServletRequest request) {
		// 根据请求查找处理器的方式有多种，需要选择合适的一种方式进行查找
		// 根据springmvc的处理流程分析，处理器的查找是委托给HandlerMapping来处理的。

		// 比如：将url和处理器的映射管理配置为bean标签的name（url）和class对应管理
		// 比如：将url和处理器的映射管理配置到bean的子标签中property中，具体是通过property的props子标签进行配置
		// <props><prop><key value="url">处理器类的全路径</key>....
		// 选择的处理，一般来说使用if语句，但是扩展性差，此处最好使用策略模式。
		if (handlerMappings != null) {
			for (HandlerMapping hm : handlerMappings) {
				Object handler = hm.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

}
